home *** CD-ROM | disk | FTP | other *** search
/ Power Programmierung 2 / Power-Programmierung CD 2 (Tewi)(1994).iso / gnu / gnulib / dkbtrace / pbmplus / source / pbm / pbmmask.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-12-10  |  5.4 KB  |  223 lines

  1. /* pbmmask.c - create a mask bitmap from a portable bitmap
  2. **
  3. ** Copyright (C) 1989, 1991 by Jef Poskanzer.
  4. **
  5. ** Permission to use, copy, modify, and distribute this software and its
  6. ** documentation for any purpose and without fee is hereby granted, provided
  7. ** that the above copyright notice appear in all copies and that both that
  8. ** copyright notice and this permission notice appear in supporting
  9. ** documentation.  This software is provided "as is" without express or
  10. ** implied warranty.
  11. */
  12.  
  13. #include "pbm.h"
  14.  
  15. static void addflood ARGS(( int col, int row ));
  16. static void flood ARGS(( void ));
  17.  
  18. static bit** bits;
  19. static bit** mask;
  20. static bit backcolor;
  21. static int rows, cols;
  22.  
  23. void
  24. main( argc, argv )
  25.     int argc;
  26.     char* argv[];
  27.     {
  28.     FILE* ifp;
  29.     int argn, expand, wcount;
  30.     register int row, col;
  31.     char* usage = "[-expand] [pbmfile]";
  32.  
  33.     pbm_init( &argc, argv );
  34.  
  35.     argn = 1;
  36.     expand = 0;
  37.  
  38.     if ( argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0' )
  39.     {
  40.     if ( pm_keymatch( argv[argn], "-expand", 2 ) )
  41.         expand = 1;
  42.     else if ( pm_keymatch( argv[argn], "-noexpand", 2 ) )
  43.         expand = 0;
  44.     else
  45.         pm_usage( usage );
  46.     ++argn;
  47.     }
  48.  
  49.     if ( argn == argc )
  50.     ifp = stdin;
  51.     else
  52.     {
  53.     ifp = pm_openr( argv[argn] );
  54.     ++argn;
  55.     }
  56.  
  57.     if ( argn != argc )
  58.     pm_usage( usage );
  59.  
  60.     bits = pbm_readpbm( ifp, &cols, &rows );
  61.     pm_close( ifp );
  62.     mask = pbm_allocarray( cols, rows );
  63.  
  64.     /* Clear out the mask. */
  65.     for ( row = 0; row < rows; ++row )
  66.         for ( col = 0; col < cols; ++col )
  67.         mask[row][col] = PBM_BLACK;
  68.  
  69.     /* Figure out the background color, by counting along the edge. */
  70.     wcount = 0;
  71.     for ( row = 0; row < rows; ++row )
  72.     {
  73.     if ( bits[row][0] == PBM_WHITE )
  74.         ++wcount;
  75.     if ( bits[row][cols - 1] == PBM_WHITE )
  76.         ++wcount;
  77.     }
  78.     for ( col = 1; col < cols - 1; ++col )
  79.     {
  80.     if ( bits[0][col] == PBM_WHITE )
  81.         ++wcount;
  82.     if ( bits[rows - 1][col] == PBM_WHITE )
  83.         ++wcount;
  84.     }
  85.     if ( wcount >= rows + cols - 2 )
  86.     backcolor = PBM_WHITE;
  87.     else
  88.     backcolor = PBM_BLACK;
  89.  
  90.     /* Flood the entire edge.  Probably the first call will be enough, but
  91.     ** might as well be sure. */
  92.     for ( col = cols - 3; col >= 2; col -= 2 )
  93.     {
  94.     addflood( col, rows - 1 );
  95.     addflood( col, 0 );
  96.     }
  97.     for ( row = rows - 1; row >= 0; row -= 2 )
  98.     {
  99.     addflood( cols - 1, row );
  100.     addflood( 0, row );
  101.     }
  102.     flood( );
  103.  
  104.     if ( ! expand )
  105.     /* Done. */
  106.     pbm_writepbm( stdout, mask, cols, rows, 0 );
  107.     else
  108.     { /* Expand by one pixel. */
  109.     register int srow, scol;
  110.     bit** emask;
  111.  
  112.     emask = pbm_allocarray( cols, rows );
  113.  
  114.     for ( row = 0; row < rows; ++row )
  115.         for ( col = 0; col < cols; ++col )
  116.         if ( mask[row][col] == PBM_BLACK )
  117.             emask[row][col] = PBM_BLACK;
  118.         else
  119.             {
  120.             emask[row][col] = PBM_WHITE;
  121.             for ( srow = row - 1; srow <= row + 1; ++srow )
  122.             for ( scol = col - 1; scol <= col + 1; ++scol )
  123.                 if ( srow >= 0 && srow < rows &&
  124.                  scol >= 0 && scol < cols &&
  125.                  mask[srow][scol] == PBM_BLACK )
  126.                 {
  127.                 emask[row][col] = PBM_BLACK;
  128.                 break;
  129.                 }
  130.             }
  131.  
  132.     /* Done. */
  133.     pbm_writepbm( stdout, emask, cols, rows, 0 );
  134.     }
  135.  
  136.     pm_close( stdout );
  137.     exit( 0 );
  138.     }
  139.  
  140. static short* fcols;
  141. static short* frows;
  142. static int fstacksize = 0, fstackp = 0;
  143.  
  144. static void
  145. addflood( col, row )
  146. int col, row;
  147.     {
  148.     if ( bits[row][col] == backcolor && mask[row][col] == PBM_BLACK )
  149.     {
  150.     if ( fstackp >= fstacksize )
  151.         {
  152.         if ( fstacksize == 0 )
  153.         {
  154.         fstacksize = 1000;
  155.         fcols = (short*) malloc( fstacksize * sizeof(short) );
  156.         frows = (short*) malloc( fstacksize * sizeof(short) );
  157.         if ( fcols == (short*) 0 || frows == (short*) 0 )
  158.             pm_error( "out of memory" );
  159.         }
  160.         else
  161.         {
  162.         fstacksize *= 2;
  163.         fcols = (short*) realloc(
  164.             (char*) fcols, fstacksize * sizeof(short) );
  165.         frows = (short*) realloc(
  166.             (char*) frows, fstacksize * sizeof(short) );
  167.         if ( fcols == (short*) 0 || frows == (short*) 0 )
  168.             pm_error( "out of memory" );
  169.         }
  170.         }
  171.     fcols[fstackp] = col;
  172.     frows[fstackp] = row;
  173.     ++fstackp;
  174.     }
  175.     }
  176.  
  177. static void
  178. flood( )
  179.     {
  180.     register int col, row, c;
  181.  
  182.     while ( fstackp > 0 )
  183.     {
  184.     --fstackp;
  185.     col = fcols[fstackp];
  186.     row = frows[fstackp];
  187.     if ( bits[row][col] == backcolor && mask[row][col] == PBM_BLACK )
  188.         {
  189.         mask[row][col] = PBM_WHITE;
  190.         if ( row - 1 >= 0 )
  191.         addflood( col, row - 1 );
  192.         if ( row + 1 < rows )
  193.         addflood( col, row + 1 );
  194.         for ( c = col + 1; c < cols; ++c )
  195.         {
  196.         if ( bits[row][c] == backcolor && mask[row][c] == PBM_BLACK )
  197.             {
  198.             mask[row][c] = PBM_WHITE;
  199.             if ( row - 1 >= 0 && ( bits[row - 1][c - 1] != backcolor || mask[row - 1][c - 1] != PBM_BLACK ) )
  200.             addflood( c, row - 1 );
  201.             if ( row + 1 < rows && ( bits[row + 1][c - 1] != backcolor || mask[row + 1][c - 1] != PBM_BLACK ) )
  202.             addflood( c, row + 1 );
  203.             }
  204.         else
  205.             break;
  206.         }
  207.         for ( c = col - 1; c >= 0; --c )
  208.         {
  209.         if ( bits[row][c] == backcolor && mask[row][c] == PBM_BLACK )
  210.             {
  211.             mask[row][c] = PBM_WHITE;
  212.             if ( row - 1 >= 0 && ( bits[row - 1][c + 1] != backcolor || mask[row - 1][c + 1] != PBM_BLACK ) )
  213.             addflood( c, row - 1 );
  214.             if ( row + 1 < rows && ( bits[row + 1][c + 1] != backcolor || mask[row + 1][c + 1] != PBM_BLACK ) )
  215.             addflood( c, row + 1 );
  216.             }
  217.         else
  218.             break;
  219.         }
  220.         }
  221.     }
  222.     }
  223.